home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / EDITSDI.PAK / PRINT.C < prev    next >
C/C++ Source or Header  |  1997-05-06  |  11KB  |  398 lines

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright (C) 1993-1995  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE: print.c
  9. //
  10. //  PURPOSE: Handle the application specific printing commands based on
  11. //    parameters gathered from the common printer dialog box.
  12. //
  13. //  FUNCTIONS:
  14. //    Print - To print a text document based on information from the common
  15. //      print dialog.
  16. //    CalcPageSize - To calculate the number of lines per page & height of a
  17. //      line.
  18. //    PrintPage - To print a single page.
  19. //    GetPageRange - To get the range of pages of a document.
  20. //    AbortProc - Processes messages for the Abort Dialog box.
  21. //    AbortDlg - Processes messages for printer abort dialog box.
  22. //
  23. //
  24. //  COMMENTS:
  25. //
  26. //  SPECIAL INSTRUCTIONS: N/A
  27. //
  28.  
  29.  
  30. #include <windows.h>            // required for all Windows applications
  31. #ifdef WIN16
  32. #include "win16ext.h"           // required only for win16 applications
  33. #endif
  34. #include "globals.h"            // prototypes specific to this application
  35. #include "resource.h"
  36. #include <string.h>
  37.  
  38.  
  39. BOOL CALLBACK AbortProc(HDC, int);
  40. LRESULT CALLBACK AbortDlg(HWND, UINT, WPARAM, LPARAM);
  41. VOID CalcPageSize(HDC);
  42. VOID PrintPage(HDC, UINT, UINT, UINT, UINT);
  43.  
  44. static HWND hdlgAbort = NULL;   // Abort dialog hanlde
  45. static BOOL fAbort = FALSE;     // Abort Flag
  46. static UINT LineSpace = 0;      // Height of line
  47. static UINT clnPage = 0;        // Number of lines per page
  48.  
  49. //
  50. //  FUNCTION:
  51. //    Print(HWND, HDC, BOOL, BOOL, BOOL, BOOL, UINT, UINT, UINT, HGLOBAL)
  52. //
  53. //  PURPOSE: To print a text document based on information from the
  54. //    common print dialog.
  55. //
  56. //  PARAMETERS:
  57. //    hwnd - The window that the print message came from.
  58. //    hdc - The display context to print to.
  59. //    fPageNums - Print the page range specified by n[From|To]Page.
  60. //    fSelection - Print the current selection.
  61. //    fCollate - Print the pages in a collated order.
  62. //    fFile - Print to a file.
  63. //    nFromPage - First page to print.  (Valid only when fPageNums == TRUE)
  64. //    nToPage - Last page to print.     (Valid only when fPageNums == TRUE)
  65. //    hDevNames -
  66. //
  67. //  RETURN VALUE:
  68. //    None.
  69. //
  70. //  COMMENTS:
  71. //
  72. //
  73.  
  74. #pragma argsused
  75. VOID Print(HWND hwnd,
  76.            HDC  hdc,
  77.            BOOL fPageNums,
  78.            BOOL fSelection,
  79.            BOOL fCollate,
  80.            BOOL fFile,
  81.            UINT nFromPage,
  82.            UINT nToPage,
  83.            UINT nCopies,
  84.            HGLOBAL hDevNames)
  85. {
  86.     HCURSOR hcurSave;
  87.     DOCINFO di;
  88.     UINT    ilnStartSel = 0;
  89.     UINT    cln;
  90.     UINT    ipg;
  91.     UINT    ipgMin;
  92.     UINT    ipgMax;
  93.  
  94.     hcurSave = SetCursor(hcursHourGlass);
  95.  
  96.     fAbort = FALSE; // Clears the abort flag
  97.  
  98.     // Define the abort function
  99.     SetAbortProc(hdc, (DLGPROC)AbortProc);
  100.  
  101.     // Start the printing session
  102.     #ifndef WIN16
  103.     ZeroMemory(&di, sizeof(DOCINFO));
  104.     #else
  105.     memset(&di, 0, sizeof(DOCINFO));
  106.     #endif
  107.     di.cbSize = sizeof(DOCINFO);
  108.     di.lpszDocName = "PrntFile text";
  109.     di.lpszOutput = NULL;
  110.     if (StartDoc(hdc, &di) < 0)
  111.     {
  112.         SetCursor(hcurSave);    // Remove the hourglass
  113.         MessageBox(hwnd, 
  114.                    "Unable to start print job", 
  115.                    NULL, 
  116.                    MB_OK | MB_ICONHAND);
  117.         DeleteDC(hdc);
  118.     }
  119.  
  120.     // Create the Abort dialog box (modeless)
  121.     hdlgAbort = CreateDialog(hInst, "AbortDlg", hwnd, (DLGPROC)AbortDlg);
  122.  
  123.     if (!hdlgAbort)
  124.     {
  125.         SetCursor(hcurSave);    // Remove the hourglass
  126.         MessageBox(hwnd, 
  127.                    "NULL Abort window handle", 
  128.                    NULL, 
  129.                    MB_OK | MB_ICONHAND);
  130.         DeleteDC(hdc);
  131.         return;
  132.     }
  133.  
  134.     // Now show Abort dialog
  135.     ShowWindow (hdlgAbort, SW_NORMAL);
  136.  
  137.     // Disable the main window to avoid reentrancy problems
  138.     EnableWindow(hwnd, FALSE);
  139.     SetCursor(hcurSave);      // Remove the hourglass
  140.  
  141.     CalcPageSize(hdc);
  142.  
  143.     // You can output only one line at a time, so you need a count of the
  144.     //  number of lines to print.  You can retrieve the count sending the
  145.     //  EM_GETLINECOUNT message to the edit control.
  146.  
  147.     // Calculate the first and last page to be printed
  148.  
  149.     if (fPageNums)
  150.     {
  151.         ipgMin = nFromPage - 1;
  152.         ipgMax = nToPage;
  153.         cln = ipgMax * clnPage;
  154.     }
  155.     else if (fSelection)
  156.     {
  157.         UINT ichStart;
  158.         UINT ichEnd;
  159.  
  160.         GETSEL(ichStart, ichEnd);
  161.  
  162.         ilnStartSel = (UINT) SendMessage(GetEditWindow(), 
  163.                                          EM_LINEFROMCHAR, 
  164.                                          ichStart, 
  165.                                          0L);
  166.         ipgMin = ilnStartSel / clnPage;
  167.         cln = (UINT) SendMessage(GetEditWindow(), 
  168.                                  EM_LINEFROMCHAR, 
  169.                                  ichEnd, 
  170.                                  0L) - ilnStartSel + 1;
  171.         ilnStartSel = ilnStartSel % clnPage;
  172.         ipgMax = ipgMin + cln / clnPage + 1;
  173.     }
  174.     else
  175.     {
  176.         cln = (UINT)SendMessage(GetEditWindow(), EM_GETLINECOUNT, 0, 0L);
  177.         ipgMin = 0;
  178.         ipgMax = cln / clnPage + 1;
  179.     }
  180.  
  181.     do
  182.     {
  183.         for (ipg = ipgMin; ipg < ipgMax && !fAbort; ipg++)
  184.         {
  185.             // If we are printing the entire document, or just a range
  186.             // of pages, ilnStartSel will be zero.  Otherwise, it's
  187.             // the 0 based offset (from the top of the given page) to 
  188.             // the first line to print 
  189.  
  190.             UINT ilnFirst = ilnStartSel;
  191.             UINT ilnLast  = ilnFirst + clnPage - 1;
  192.  
  193.             // Special case last page
  194.             if (ipg == ipgMax-1)
  195.             {
  196.                 ilnLast = ilnFirst + ((cln-1) % clnPage);
  197.             }
  198.  
  199.             PrintPage(hdc, ipg, ilnFirst, ilnLast, fCollate ? 1 : nCopies);
  200.         }
  201.     } while (fCollate && --nCopies > 0);
  202.     EndDoc(hdc);
  203.  
  204.     EnableWindow(hwnd, TRUE);
  205.  
  206.     // Destroy the Abort dialog box
  207.  
  208.     DestroyWindow(hdlgAbort);
  209.     DeleteDC(hdc);
  210. }
  211.  
  212. //
  213. //  FUNCTION: CalcPageSize(HDC)
  214. //
  215. //  PURPOSE: To calculate the number of lines per page & height of a line.
  216. //
  217. //  PARAMETERS:
  218. //    hdc - The printer device context used to calculate the sizes.
  219. //
  220. //  RETURN VALUE:
  221. //    NONE
  222. //
  223. //  COMMENTS:
  224. //    Sets the module static variable LineSpace and clnPage to the
  225. //    Height of a line and the number of lines per page, respectively.
  226. //
  227.  
  228. VOID CalcPageSize(HDC hdc)
  229. {
  230.     TEXTMETRIC tm;
  231.     UINT nPageSize;
  232.  
  233.     // Since you may have more than one line, you need to
  234.     //   compute the spacing between lines.  You can do that by
  235.     //   retrieving the height of the characters you are printing
  236.     //   and advancing their height plus the recommended external
  237.     //   leading height.
  238.  
  239.     GetTextMetrics(hdc, &tm);
  240.     LineSpace = tm.tmHeight + tm.tmExternalLeading;
  241.  
  242.     // Since you may have more lines than can fit on one page, you need
  243.     //  to compute the number of lines you can print per page.  You can
  244.     //  do that by retrieving the dimensions of the page and dividing
  245.     //  the height by the line spacing.
  246.  
  247.     nPageSize = GetDeviceCaps(hdc, VERTRES);
  248.     clnPage = nPageSize / LineSpace - 1;
  249. }
  250.  
  251. //
  252. //  FUNCTION: PrintPage(HDC, UING, UINJT, UINT, UINT)
  253. //
  254. //  PURPOSE: To print a single page.
  255. //
  256. //  PARAMETERS:
  257. //    hdc - The printer device context to print on.
  258. //    ipg - The zero based index of the page to print.
  259. //    iln - The zero based index of the first line on the page to print.
  260. //    ilnEnd - The zero based index of the last line on the page to print.
  261. //    nCopies - The number of copies to print.
  262. //
  263. //  RETURN VALUE:
  264. //    NONE
  265. //
  266. //  COMMENTS:
  267. //
  268. //
  269.  
  270. VOID PrintPage(HDC hdc, UINT ipg, UINT ilnStart, UINT ilnEnd, UINT nCopies)
  271. {
  272.     UINT ilnBase = ipg * clnPage;
  273.  
  274.     while (nCopies-- > 0)
  275.     {
  276.         UINT iln = 0;
  277.  
  278.         StartPage(hdc);
  279.         while(iln + ilnStart <= ilnEnd)
  280.         {
  281.             char szLine[128];
  282.             int  cchLine;
  283.  
  284.             szLine[0] = sizeof(szLine)-1;          // Maximum buffer size
  285.             szLine[1] = 0;
  286.             cchLine = (int)SendMessage(GetEditWindow(),
  287.                                        EM_GETLINE,
  288.                                        ilnBase + iln + ilnStart,
  289.                                        (DWORD)(LPSTR)szLine);
  290.             TextOut(hdc, 0, iln*LineSpace, (LPSTR)szLine, cchLine);
  291.             iln += 1;
  292.         }
  293.         EndPage(hdc);
  294.     }
  295. }
  296.  
  297. //
  298. //  FUNCTION: GetPageRange(VOID);
  299. //
  300. //  PURPOSE: To get the range of pages of a document.
  301. //
  302. //  PARAMETERS:
  303. //
  304. //  RETURN VALUE:
  305. //
  306. //  COMMENTS:
  307. //
  308. //
  309.  
  310. DWORD GetPageRange(VOID)
  311. {
  312.     return (DWORD) MAKELONG(1,0xFFFF);
  313. }
  314.  
  315.  
  316. //
  317. //  FUNCTION: AbortProc(HDC, int)
  318. //
  319. //  PURPOSE: Processes messages for the Abort Dialog box.
  320. //
  321. //  PARAMETERS:
  322. //    hdc - The printer device context used to calculate the sizes.
  323. //    Code -  The error code
  324. //
  325. //  RETURN VALUE:
  326. //    Returns FALSE if the user has aborted, TRUE otherwise.
  327. //
  328. //  COMMENTS:
  329. //
  330. //
  331.  
  332. #pragma argsused
  333. BOOL CALLBACK AbortProc(HDC hdc, int Code)
  334. {
  335.      MSG msg;
  336.  
  337.      if (!hdlgAbort)              // If the abort dialog isn't up yet
  338.           return TRUE;
  339.  
  340.     // Process messages intended for the abort dialog box
  341.  
  342.     while (!fAbort && PeekMessage(&msg, NULL, 0, 0, TRUE))
  343.         if (!IsDialogMessage(hdlgAbort, &msg))
  344.         {
  345.             TranslateMessage(&msg);
  346.             DispatchMessage(&msg);
  347.         }
  348.  
  349.     // fAbort is TRUE (return is FALSE) if the user has aborted
  350.  
  351.      return !fAbort;
  352. }
  353.  
  354. //
  355. //  FUNCTION: AbortDlg(HWND, UINT, WPARAM, LPARAM)
  356. //
  357. //  PURPOSE: Processes messages for printer abort dialog box.
  358. //
  359. //  PARAMETERS:
  360. //    hdlg   - The dialog handle.
  361. //    msg    - The message number.
  362. //    wparam - Message specific data.
  363. //    lparam -  Message specific data.
  364. //
  365. //  RETURN VALUE:
  366. //    Depends on the message number.
  367. //
  368. //  COMMENTS:
  369. //      This dialog box is created while the program is printing, and allows
  370. //      the user to cancel the printing process.
  371. //
  372.  
  373. #pragma argsused
  374. LRESULT CALLBACK AbortDlg(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
  375. {
  376.  
  377.     switch(msg)
  378.     {
  379.         // Watch for Cancel button, RETURN key, ESCAPE key, or SPACE BAR
  380.  
  381.         case WM_COMMAND:
  382.                 return fAbort = TRUE;
  383.  
  384.         case WM_INITDIALOG:
  385.  
  386.             // Set the focus to the Cancel box of the dialog
  387.  
  388.             SetFocus(GetDlgItem(hdlg, IDCANCEL));
  389. #ifdef WIN16
  390.             SetDlgItemText(hdlg, IDC_FILENAME, (LPSTR) GetFName());
  391. #else
  392.             SetDlgItemText(hdlg, IDC_FILENAME, (LPCTSTR) GetFName());
  393. #endif
  394.             return TRUE;
  395.      }
  396.     return FALSE;
  397. }
  398.